package me.zhengjie.modules.hanzi.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import me.zhengjie.modules.hanzi.domain.HanziCharacter;
import me.zhengjie.modules.hanzi.mapper.CharacterMapper;
import me.zhengjie.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CharacterService extends ServiceImpl<CharacterMapper, HanziCharacter> {
    private final CharacterMapper characterMapper;

    private final StrokeService strokeService;

    @Autowired
    @Qualifier("hanziThreadPool")
    private ThreadPoolTaskExecutor hanziThreadPool;

    public Page<HanziCharacter> getCharacters(int page, int limit, String level) {
        QueryWrapper<HanziCharacter> wrapper = new QueryWrapper<>();
        if (level != null) {
            wrapper.eq("level", level);
        }
        wrapper.orderByAsc("stroke_count");
        return characterMapper.selectPage(new Page<>(page, limit), wrapper);
    }

    public HanziCharacter getCharacter(String character) {
        QueryWrapper<HanziCharacter> wrapper = new QueryWrapper<>();
        wrapper.eq("`character`", character);
        return characterMapper.selectOne(wrapper);
    }

    public HanziCharacter getDailyCharacter() {
        LocalDate today = LocalDate.now();
        int seed = today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth();

        return characterMapper.selectOne(new QueryWrapper<HanziCharacter>()
                .select("character", "pinyin", "meaning")
                .last("ORDER BY RAND(" + seed + ") LIMIT 1"));
    }

    @Transactional(rollbackFor = Exception.class)
    public void initCharacter() {
        List<HanziCharacter> hanziCharacters = this.list();
        if (CollectionUtil.isEmpty(hanziCharacters)) {
            ClassPathResource resource = new ClassPathResource("hanzi/hanzi.txt");

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {

                List<String> stringList = reader.lines().collect(Collectors.toList());
                Set<HanziCharacter> characterList = new HashSet<>();

                // 分批处理，避免一次提交过多任务
                int batchSize = 100; // 每批提交100个任务
                List<List<String>> partitionList = ListUtil.partition(stringList, batchSize);
                for (List<String> batch : partitionList) {
                    List<Future<HanziCharacter>> futureList = new ArrayList<>();

                    for (String s : batch) {
                        futureList.add(hanziThreadPool.submit(() -> {
                            HanziCharacter hanziCharacter = new HanziCharacter();
                            if (s.contains(" ") && !s.endsWith(" ")){
                                String[] strings = s.split(" ");
                                hanziCharacter.setCharacter(strings[0]);
                                hanziCharacter.setCategoryId(strings[1]);
                            }
                            else {
                                hanziCharacter.setCategoryId("1");
                                hanziCharacter.setCharacter(s);
                            }

                            Map<String, Object> strokeGif = strokeService.getStrokeGif(s);
                            Map detailMap = (Map) strokeGif.get("detail");

                            if (CollectionUtil.isNotEmpty(detailMap)) {
                                // 拼音
                                List pinyinList = (List) detailMap.get("pinyinList");
                                if (CollectionUtil.isNotEmpty(pinyinList)) {
                                    Map pinyinMap = (Map) pinyinList.get(0);
                                    hanziCharacter.setPinyin(pinyinMap.get("name").toString());
                                }

                                // 笔顺数据
                                List strokeOrderList = (List) detailMap.get("strokeOrder");
                                if (CollectionUtil.isNotEmpty(strokeOrderList)){
                                    hanziCharacter.setStrokeCount(strokeOrderList.size());
                                }

                                // 年级等级判断
                                Object lessonInfo = detailMap.get("lessonInfo");
                                if (lessonInfo instanceof List) {
//                                hanziCharacter.setLevel(1);
                                } else if (lessonInfo instanceof Map) {
                                    Map lessMap = (Map) lessonInfo;
                                    Object grade = lessMap.get("grade");
                                    if (Objects.nonNull(grade)) {
                                        int level = StringUtils.extractGradeNumber(grade.toString());
                                        hanziCharacter.setLevel(level);
                                    }
                                }
                            }

                            return hanziCharacter;
                        }));
                    }

                    // 等待当前批次所有任务完成
                    for (Future<HanziCharacter> future : futureList) {
                        try {
                            characterList.add(future.get());
                        } catch (Exception e) {
                            e.printStackTrace(); // 单个失败不影响整体
                        }
                    }
                }

                this.saveBatch(characterList);
            } catch (Exception e) {
                throw new RuntimeException("初始化汉字失败", e);
            }
        }
    }

}